<!--
  智慧社区管理系统 - 操作日志
  @author Wu.Liang
  @date 2024-01-01
  @updated 2025-07-28 - 设计美观的操作日志页面
-->
<template>
    <div class="operation-log">
        <!-- 页面标题和描述 -->
        <div class="page-header">
            <div class="page-title">
                <h1>操作日志</h1>
                <p class="page-desc">记录系统用户的操作行为，包括登录、数据增删改查等操作记录</p>
            </div>
            <div class="page-actions">
                <el-button type="primary" :icon="Download" @click="handleExport">
                    导出日志
                </el-button>
                <el-button :icon="Delete" @click="handleClear" type="danger">
                    清空日志
                </el-button>
            </div>
        </div>

        <!-- 搜索和筛选区域 -->
        <el-card class="search-card" shadow="never">
            <el-form :model="searchForm" inline class="search-form">
                <el-form-item label="操作类型">
                    <el-select 
                        v-model="searchForm.operationType" 
                        placeholder="请选择操作类型"
                        clearable
                        style="width: 150px"
                    >
                        <el-option label="登录" value="LOGIN" />
                        <el-option label="登出" value="LOGOUT" />
                        <el-option label="新增" value="CREATE" />
                        <el-option label="修改" value="UPDATE" />
                        <el-option label="删除" value="DELETE" />
                        <el-option label="查询" value="QUERY" />
                        <el-option label="导出" value="EXPORT" />
                        <el-option label="导入" value="IMPORT" />
                    </el-select>
                </el-form-item>
                
                <el-form-item label="操作人">
                    <el-input 
                        v-model="searchForm.operator" 
                        placeholder="请输入操作人姓名"
                        clearable
                        style="width: 150px"
                    />
                </el-form-item>
                
                <el-form-item label="操作状态">
                    <el-select 
                        v-model="searchForm.status" 
                        placeholder="请选择状态"
                        clearable
                        style="width: 120px"
                    >
                        <el-option label="成功" :value="1" />
                        <el-option label="失败" :value="0" />
                    </el-select>
                </el-form-item>
                
                <el-form-item label="操作时间">
                    <el-date-picker
                        v-model="searchForm.timeRange"
                        type="datetimerange"
                        range-separator="至"
                        start-placeholder="开始时间"
                        end-placeholder="结束时间"
                        format="YYYY-MM-DD HH:mm:ss"
                        value-format="YYYY-MM-DD HH:mm:ss"
                        style="width: 320px"
                    />
                </el-form-item>
                
                <el-form-item>
                    <el-button type="primary" :icon="Search" @click="debouncedSearch">
                        搜索
                    </el-button>
                    <el-button :icon="Refresh" @click="handleReset">
                        重置
                    </el-button>
                </el-form-item>
            </el-form>
        </el-card>

        <!-- 日志列表区域 -->
        <el-card class="log-card" shadow="never">
            <template #header>
                <div class="card-header">
                    <span class="card-title">操作日志列表</span>
                    <div class="card-actions">
                        <el-tag type="info" size="small">
                            共 {{ total }} 条记录
                        </el-tag>
                    </div>
                </div>
            </template>
            
            <el-table 
                :data="logList" 
                border 
                stripe
                v-loading="loading"
                style="width: 100%"
            >
                <el-table-column prop="id" label="ID" width="80" align="center" />
                
                <el-table-column prop="operationType" label="操作类型" width="100" align="center">
                    <template #default="{ row }">
                        <el-tag 
                            :type="getOperationTypeTag(row.operationType)"
                            size="small"
                        >
                            {{ getOperationTypeLabel(row.operationType) }}
                        </el-tag>
                    </template>
                </el-table-column>
                
                <el-table-column prop="operationName" label="操作名称" width="150" />
                
                <el-table-column prop="operator" label="操作人" width="120" />
                
                <el-table-column prop="operatorIp" label="IP地址" width="130" />
                
                <el-table-column prop="requestUrl" label="请求地址" min-width="200" show-overflow-tooltip />
                
                <el-table-column prop="requestMethod" label="请求方法" width="80" align="center">
                    <template #default="{ row }">
                        <el-tag 
                            :type="getMethodTag(row.requestMethod)"
                            size="small"
                        >
                            {{ row.requestMethod }}
                        </el-tag>
                    </template>
                </el-table-column>
                
                <el-table-column prop="status" label="状态" width="80" align="center">
                    <template #default="{ row }">
                        <el-tag 
                            :type="getStatusTag(row.status)"
                            size="small"
                        >
                            {{ getStatusLabel(row.status) }}
                        </el-tag>
                    </template>
                </el-table-column>
                
                <el-table-column prop="duration" label="耗时" width="100" align="center">
                    <template #default="{ row }">
                        <span :class="getDurationClass(row.duration)">
                            {{ row.duration }}ms
                        </span>
                    </template>
                </el-table-column>
                
                <el-table-column prop="createTime" label="操作时间" width="180" align="center" />
                
                <el-table-column label="操作" width="120" align="center" fixed="right">
                    <template #default="{ row }">
                        <el-button 
                            type="primary" 
                            size="small" 
                            :icon="View"
                            @click="handleView(row)"
                        >
                            详情
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
            
            <!-- 分页 -->
            <div class="pagination-wrapper">
                <el-pagination
                    v-model:current-page="pagination.current"
                    v-model:page-size="pagination.size"
                    :page-sizes="[10, 20, 50, 100]"
                    :total="total"
                    layout="total, sizes, prev, pager, next, jumper"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                />
            </div>
        </el-card>

        <!-- 日志详情弹窗 -->
        <el-dialog
            v-model="detailVisible"
            title="操作日志详情"
            width="800px"
            :close-on-click-modal="false"
        >
            <div v-if="currentLog" class="log-detail">
                <el-descriptions :column="2" border>
                    <el-descriptions-item label="操作ID">
                        {{ currentLog.id }}
                    </el-descriptions-item>
                    <el-descriptions-item label="操作类型">
                        <el-tag :type="getOperationTypeTag(currentLog.operationType)">
                            {{ getOperationTypeLabel(currentLog.operationType) }}
                        </el-tag>
                    </el-descriptions-item>
                    <el-descriptions-item label="操作名称">
                        {{ currentLog.operationName }}
                    </el-descriptions-item>
                    <el-descriptions-item label="操作人">
                        {{ currentLog.operator }}
                    </el-descriptions-item>
                    <el-descriptions-item label="IP地址">
                        {{ currentLog.operatorIp }}
                    </el-descriptions-item>
                    <el-descriptions-item label="请求方法">
                        <el-tag :type="getMethodTag(currentLog.requestMethod)">
                            {{ currentLog.requestMethod }}
                        </el-tag>
                    </el-descriptions-item>
                    <el-descriptions-item label="请求地址">
                        {{ currentLog.requestUrl }}
                    </el-descriptions-item>
                    <el-descriptions-item label="操作状态">
                        <el-tag :type="getStatusTag(currentLog.status)">
                            {{ getStatusLabel(currentLog.status) }}
                        </el-tag>
                    </el-descriptions-item>
                    <el-descriptions-item label="耗时">
                        <span :class="getDurationClass(currentLog.duration)">
                            {{ currentLog.duration }}ms
                        </span>
                    </el-descriptions-item>
                    <el-descriptions-item label="操作时间">
                        {{ currentLog.createTime }}
                    </el-descriptions-item>
                    <el-descriptions-item label="用户代理">
                        {{ currentLog.userAgent }}
                    </el-descriptions-item>
                </el-descriptions>
                
                <div class="detail-section">
                    <h4>请求参数</h4>
                    <el-input
                        v-model="currentLog.requestParams"
                        type="textarea"
                        :rows="4"
                        readonly
                        placeholder="无请求参数"
                    />
                </div>
                
                <div class="detail-section">
                    <h4>响应结果</h4>
                    <el-input
                        v-model="currentLog.responseResult"
                        type="textarea"
                        :rows="4"
                        readonly
                        placeholder="无响应结果"
                    />
                </div>
                
                <div v-if="currentLog.errorMessage" class="detail-section">
                    <h4>错误信息</h4>
                    <el-input
                        v-model="currentLog.errorMessage"
                        type="textarea"
                        :rows="3"
                        readonly
                        class="error-message"
                    />
                </div>
            </div>
            
            <template #footer>
                <el-button @click="detailVisible = false">关闭</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { 
    Search, 
    Refresh, 
    Download, 
    Delete, 
    View 
} from '@element-plus/icons-vue'
import { getSystemLogList, exportSystemLog, clearSystemLog, type SystemLogQueryParams, type SystemLog } from '@/api/user'

// 搜索表单
const searchForm = reactive({
    operationType: undefined as string | undefined,
    operator: '',
    status: undefined as number | undefined,
    timeRange: [] as string[]
})

// 分页配置
const pagination = reactive({
    current: 1,
    size: 20
})

// 数据状态
const loading = ref(false)
const total = ref(0)
const logList = ref<any[]>([])
const detailVisible = ref(false)
const currentLog = ref<any>(null)

// 获取操作类型标签样式
const getOperationTypeTag = (type: string) => {
    const typeMap: Record<string, string> = {
        'LOGIN': 'success',
        'LOGOUT': 'info',
        'CREATE': 'primary',
        'UPDATE': 'warning',
        'DELETE': 'danger',
        'QUERY': 'info',
        'EXPORT': 'success',
        'IMPORT': 'warning'
    }
    return typeMap[type] || 'info'
}

// 获取操作类型标签文本
const getOperationTypeLabel = (type: string) => {
    const typeMap: Record<string, string> = {
        'LOGIN': '登录',
        'LOGOUT': '登出',
        'CREATE': '新增',
        'UPDATE': '修改',
        'DELETE': '删除',
        'QUERY': '查询',
        'EXPORT': '导出',
        'IMPORT': '导入'
    }
    return typeMap[type] || type
}

// 获取请求方法标签样式
const getMethodTag = (method: string) => {
    const tagMap: Record<string, string> = {
        'GET': 'success',
        'POST': 'primary',
        'PUT': 'warning',
        'DELETE': 'danger'
    }
    return tagMap[method] || 'info'
}

// 获取耗时样式
const getDurationClass = (duration: number) => {
    if (duration < 100) return 'duration-fast'
    if (duration < 500) return 'duration-normal'
    return 'duration-slow'
}

// 获取状态标签样式
const getStatusTag = (status: number) => {
    return status === 1 ? 'success' : 'danger'
}

// 获取状态标签文本
const getStatusLabel = (status: number) => {
    return status === 1 ? '成功' : '失败'
}

// 分页大小改变
const handleSizeChange = (size: number) => {
    pagination.size = size
    pagination.current = 1
    fetchLogList()
}

// 当前页改变
const handleCurrentChange = (current: number) => {
    pagination.current = current
    fetchLogList()
}

// 获取日志列表
const fetchLogList = async () => {
    loading.value = true
    
    try {
        // 构建查询参数
        const params: SystemLogQueryParams = {
            current: pagination.current,
            size: pagination.size,
            username: searchForm.operator || undefined,
            operationType: searchForm.operationType || undefined,
            startTime: searchForm.timeRange?.[0] || undefined,
            endTime: searchForm.timeRange?.[1] || undefined,
            logType: 2 // 操作日志类型
        }
        
        // 调用后端API获取系统日志列表
        const response = await getSystemLogList(params)
        
        if (response.data) {
            // 转换为操作日志格式
            logList.value = response.data.records.map((log: SystemLog) => ({
                id: log.id,
                operationType: log.operationName || '',
                operationName: log.logTitle || '',
                operator: log.username || '',
                operatorIp: log.ipAddress || '',
                requestUrl: log.requestUrl || '',
                requestMethod: log.requestMethod || '',
                status: log.status || 1,
                duration: log.executionTime || 0,
                createTime: log.logTime || log.createTime || '',
                userAgent: log.userAgent || '',
                requestParams: log.requestParams || '',
                responseResult: log.responseResult || '',
                errorMessage: log.errorMessage || ''
            }))
            total.value = response.data.total
            
            // 如果没有数据，显示提示信息
            if (response.data.total === 0) {
                ElMessage.info('暂无操作日志数据')
            }
        }
        
    } catch (error: any) {
        console.error('获取操作日志失败:', error)
        
        // 根据错误类型显示不同的提示信息
        if (error.response) {
            const { status, data } = error.response
            switch (status) {
                case 401:
                    // 优先使用后端返回的错误消息，如果没有则使用默认消息
                    ElMessage.error(data?.message || data?.msg || '登录已过期，请重新登录')
                    break
                case 403:
                    ElMessage.error('无权限访问操作日志')
                    break
                case 404:
                    ElMessage.error('操作日志接口不存在')
                    break
                case 500:
                    ElMessage.error('服务器内部错误，请联系管理员')
                    break
                default:
                    ElMessage.error(data?.message || '获取操作日志失败')
            }
        } else if (error.request) {
            ElMessage.error('网络连接失败，请检查网络设置')
        } else {
            ElMessage.error('获取操作日志失败：' + (error.message || '未知错误'))
        }
        
        // 清空数据
        logList.value = []
        total.value = 0
    } finally {
        loading.value = false
    }
}

// 防抖搜索
let searchTimer: NodeJS.Timeout | null = null
const debouncedSearch = () => {
    if (searchTimer) {
        clearTimeout(searchTimer)
    }
    searchTimer = setTimeout(() => {
        handleSearch()
    }, 300)
}

// 搜索
const handleSearch = () => {
    pagination.current = 1
    fetchLogList()
}

// 重置
const handleReset = () => {
    Object.assign(searchForm, {
        operationType: undefined,
        operator: '',
        status: undefined,
        timeRange: []
    })
    pagination.current = 1
    fetchLogList()
}

// 刷新
const handleRefresh = () => {
    fetchLogList()
}

// 导出日志
const handleExport = async () => {
    try {
        // 构建查询参数
        const params: SystemLogQueryParams = {
            current: 1,
            size: 10000, // 导出所有数据
            username: searchForm.operator || undefined,
            operationType: searchForm.operationType || undefined,
            startTime: searchForm.timeRange?.[0] || undefined,
            endTime: searchForm.timeRange?.[1] || undefined,
            logType: 2 // 操作日志类型
        }
        
        const response = await exportSystemLog(params)
        ElMessage.success(response.data || '导出成功')
    } catch (error: any) {
        console.error('导出失败:', error)
        ElMessage.error('导出失败：' + (error.message || '未知错误'))
    }
}

// 清空日志
const handleClear = async () => {
    try {
        await ElMessageBox.confirm('确定要清空所有操作日志吗？此操作不可恢复！', '警告', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        })
        
        await clearSystemLog()
        ElMessage.success('清空成功')
        fetchLogList() // 刷新列表
    } catch (error: any) {
        if (error !== 'cancel') {
            console.error('清空失败:', error)
            ElMessage.error('清空失败：' + (error.message || '未知错误'))
        }
    }
}

// 查看详情
const handleView = (row: any) => {
    currentLog.value = row
    detailVisible.value = true
}

// 格式化JSON
const formatJson = (json: string) => {
    try {
        return JSON.stringify(JSON.parse(json), null, 2)
    } catch {
        return json
    }
}

// 页面加载时获取数据
onMounted(() => {
    fetchLogList()
})
</script>

<style scoped>
.operation-log {
    padding: 20px;
    background-color: #f5f7fa;
    min-height: calc(100vh - 120px);
}

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 20px;
    padding: 20px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.page-title h1 {
    margin: 0 0 8px 0;
    font-size: 24px;
    font-weight: 600;
    color: #303133;
}

.page-desc {
    margin: 0;
    color: #606266;
    font-size: 14px;
}

.page-actions {
    display: flex;
    gap: 12px;
}

.search-card {
    margin-bottom: 20px;
}

.search-form {
    margin: 0;
}

.log-card {
    margin-bottom: 20px;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
}

.card-actions {
    display: flex;
    gap: 12px;
}

.pagination-wrapper {
    display: flex;
    justify-content: center;
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #f0f0f0;
}

.log-detail {
    padding: 20px 0;
}

.detail-section {
    margin-top: 20px;
}

.detail-section h4 {
    margin: 0 0 12px 0;
    font-size: 14px;
    font-weight: 600;
    color: #303133;
}

.error-message :deep(.el-textarea__inner) {
    color: #f56c6c;
    background-color: #fef0f0;
}

.duration-fast {
    color: #67c23a;
    font-weight: 500;
}

.duration-normal {
    color: #e6a23c;
    font-weight: 500;
}

.duration-slow {
    color: #f56c6c;
    font-weight: 500;
}

:deep(.el-table .el-table__cell) {
    padding: 8px 0;
}

:deep(.el-descriptions__label) {
    font-weight: 500;
    color: #303133;
}
</style>
